package com.hmdp.utils;

import cn.hutool.core.lang.UUID;
import com.fasterxml.jackson.databind.ser.std.StdKeySerializers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.concurrent.TimeUnit;


public class SimpleRedisLock implements ILock{

    private StringRedisTemplate stringRedisTemplate;
//    获取锁的方法
//    Redis锁的Key在不同的业务中有不同的key
//  所以需要定义一个业务name当做key
    private String name;

//    业务前缀
    private static final String KEY_PREFIX="lock:";
    private static final String ID_PREFIX = UUID.randomUUID().toString(true)+"-";
    private static  final DefaultRedisScript<Long> UNLOCK_SCRIPT;
    static{
        UNLOCK_SCRIPT =new DefaultRedisScript<>();
//        设置脚本的位置
        UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
        UNLOCK_SCRIPT.setResultType(Long.class);
    }
    public SimpleRedisLock(StringRedisTemplate stringRedisTemplate, String name) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.name = name;


    }

    @Override
    public boolean tryLock(long timeout) {
//        获取线程标识
        long id = Thread.currentThread().getId();
        String lockValue = ID_PREFIX+id;
        Boolean isLock = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, lockValue,timeout, TimeUnit.SECONDS);
//        由于自动拆箱会有空指针的可能 所以用以下逻辑
        return Boolean.TRUE.equals(isLock);
    }
//    释放锁的方法
//    @Override
//    public void unLock() {
////        防止误删所以加入标识判断功能
//        long id = Thread.currentThread().getId();
//        String lockValue = id+ID_PREFIX;
//        String valueFromRedis = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);
//        if (lockValue.equals(valueFromRedis)){
//            stringRedisTemplate.delete(KEY_PREFIX + name);
//        }
//    }
//    基于lua脚本进行释放锁操作
    public void unLock() {
//        调用LUA脚本
        stringRedisTemplate.execute(
                UNLOCK_SCRIPT,
                Collections.singletonList(KEY_PREFIX + name),
                ID_PREFIX+Thread.currentThread().getId());
    }
}
